/**
 * 
 */
package dk.dtu.is.utility.jess;

import java.util.Timer;
import java.util.TimerTask;

import dk.dtu.is.main.java.RunPowerlabClientMVC;
import dk.dtu.is.model.iec61850.ln.Zcev;
import jess.*;

/**
 * This is the UserFunction for Jess which will connect to the IEC 61850 server and update the Zcev JavaBean.
 * 
 * The address and other connecting details are specified in the "PowerlabClientSettings.xml" file.
 * 
 * @author dsac
 */
public class StartIec61850ServerPolling extends TimerTask implements Userfunction {
	
	/**
	 * This is the name that Jess will be using to spot this function
	 */
	private static final String functionName = "start-iec61850-serverpolling";
	
	/**
	 * This si the main controller of the app.
	 * It creates the proper objects and takes care of the handling of the connection with the server
	 */
	private RunPowerlabClientMVC runPowerlabClientMVC;
	
	/**
	 * This is the JavaBean which contains the data retrived from the IEC61850 server related to the table2grid 
	 */
	private Zcev zcev = null;

	/**
	 * This method runs when this function is being invoked by JESS
	 * Override of Userfunction
	 */
	@Override
	public Value call(ValueVector vv, Context context) throws JessException {
		if (vv.size() > 1) 
			throw new JessException(functionName,"No arguments are required for this fuction. Invalid number of arguments: ",vv.size() - 1);
		
		// create an instance of the main controller of the app.
		// this class will be sued to retrieve data from the server using the poller
		runPowerlabClientMVC = new RunPowerlabClientMVC();
		
		// I create a timer which will trigger every 5 seconds. The timer will trigger the method "run" in this class
		// where a new reading from the server is being retrieved
		Timer pollIec61850Server = new Timer();
		pollIec61850Server.schedule(this, 5*1000, 5*1000);
		
		// create the first Zcev.
		zcev = runPowerlabClientMVC.getZcevFromResponse(runPowerlabClientMVC.getIec61850ServerResponse());;
		
		// get the rete engine of the current context
		// if you had instantiated another Rete engine here, you would get another Rete object which does not reflect your system status
		Rete rete = context.getEngine();
		// the JavaBean in Jess gets now mapped into this Zcev Java object.
		// the instance of Zcev in Jess is the same as this one.
		rete.definstance("Zcev", zcev, true);
		
		return null;
	}

	/**
	 * The name that will be used to call this function in JESS
	 */
	@Override
	public String getName() {
		return functionName;
	}

	
	/**
	 * Polls the server at specific intervals and update the JavaBean Zcev
	 * 
	 * Override for the TimerTask class
	 */
	@Override
	public void run() {
		Zcev newZcev = runPowerlabClientMVC.getZcevFromResponse(runPowerlabClientMVC.getIec61850ServerResponse());
		
		// it is necessary to do it this way because if I had written this.zcev = newZcev, the property change event does not get fired.
		this.zcev.setCur(newZcev.getCur());
		this.zcev.setVol(newZcev.getVol());
		this.zcev.setSoc(newZcev.getSoc());
	}

}
